﻿//////////////////////////////////////////////////////////////////
//
// Almanac.cs
//
// Copyright (c) 2012 Dan Pike.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Utilities;

namespace Almanac
{
   internal class Almanac : IAlmanac
   {
      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      private static Logger logger_;
      private List<IPlanetFact> planets_;
      private List<IMaterialFact> materials_;
      private List<IProducerFact> producers_;
      private List<IScriptFile> scripts_;
      private DateTime now_ = DateTime.Now;  //¬¬¬ Update this each time round the loop

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      public Almanac()
      {
         // DON'T INITIALIZE THE LOGGER HERE; IT DOES NOT EXIST YET!

         // The Almanac is constructed during program initialization before any
         // of the global data has been initialized. so we can't do anything here
         // that depends on the debug logger or config or anything like that.
         // Put such code in the initialize() method, which is called after the
         // Program static variables have been set.
         planets_ = new List<IPlanetFact>();
         materials_ = new List<IMaterialFact>();
         producers_ = new List<IProducerFact>();
         scripts_ = new List<IScriptFile>();
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Implementation of IAlmanac
      /// </summary>
      /// <returns></returns>
      public bool Initialize()
      {
         try
         {
            // MUST DO THIS HERE NOT IN THE CONSTRUCTOR!
            logger_ = Program.Logger;

            logger_.Debug("initializing almanac");

            // Compile all of the scripts
            logger_.Debug("compiling scripts");
            if (!Program.Settings.ScriptFiles.Value.OfType<Config.ScriptFile>()
               .Where(configScriptFile => configScriptFile.Active).ToList()
                  .All(configScriptFile =>
                  {
                     IScriptFile scriptFile = Program.Loader.Create<IScriptFile>();
                     string scriptName = configScriptFile.Filename;
                     if (!scriptFile.Compile(scriptName))
                     {
                        return false;
                     }
                     scripts_.Add(scriptFile);
                     return true;
                  }))
            {
               logger_.Error("failed to compile one or more of the scripts");
               return false;
            }
            logger_.DebugFormat("all scripts compiled successfully");
            return true;
         }
         catch (System.Exception ex)
         {
            logger_.Exception(ex);
         }
         return false;
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Implementation of IAlmanac
      /// </summary>
      public DateTime Now
      {
         get { return now_; }
         set { now_ = value; }
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Implementation of IAlmanac
      /// </summary>
      public IList<IScriptFile> Scripts
      {
         get { return scripts_; }
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Implementation of IAlmanac
      /// </summary>
      public IList<IPlanetFact> Planets
      {
         get { return planets_; }
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Implementation of IAlmanac
      /// </summary>
      public IList<IMaterialFact> Materials
      {
         get { return materials_; }
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Implementation of IAlmanac
      /// </summary>
      public IList<IProducerFact> Producers
      {
         get { return producers_; }
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Implementation of IAlmanac
      /// </summary>
      public IProducerFact FindProducer(string name)
      {
         return producers_.FirstOrDefault(producer => producer.DisplayName == name);
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Implementation of IAlmanac
      /// </summary>
      public IMaterialFact FindMaterial(string name)
      {
         return materials_.FirstOrDefault(material => material.DisplayName == name);
      }
   }
}
